#include "characterwidget.h"
#include "ui_characterwidget.h"

#include "../namegiver.h"
#include "../adept.h"
#include "../database.h"

#include <QDomDocument>

QString levelString(int level)
{
  return QString::number(level) + " / " + ed::poolString(Database::dicePool(level));
}

CharacterWidget::CharacterWidget(QWidget *parent) :
  QWidget(parent),
  ui(new Ui::CharacterWidget)
{
  ui->setupUi(this);
}

CharacterWidget::~CharacterWidget()
{
  delete ui;
}

QString CharacterWidget::csv() const
{
  return _csv;
}

QString CharacterWidget::idd() const
{
  return _idd;
}

void CharacterWidget::setCharacter(Character* c)
{
  clear();

  NameGiver* ng = dynamic_cast<NameGiver*>(c);
  Adept* a = dynamic_cast<Adept*>(c);
  bool isAdept = (a != nullptr);
  if (ng == nullptr) return;

  ui->lbl_name->setText(ng->name());
  ui->lbl_race->setText((QString)ng->race());
  QVector<QLabel*> attrLabels;
  attrLabels.push_back(ui->lbl_DEX);
  attrLabels.push_back(ui->lbl_FOR);
  attrLabels.push_back(ui->lbl_CON);
  attrLabels.push_back(ui->lbl_PER);
  attrLabels.push_back(ui->lbl_VOL);
  attrLabels.push_back(ui->lbl_CHA);
  int i=0;
  foreach(ed::Attribute a, ed::Attribute::values())
  {
    attrLabels[i++]->setText(levelString(ng->attributeLevel(a)));
  }

  foreach(const Skill& s, ng->skills().keys())
  {
    ui->lbl_skills->setText(ui->lbl_skills->text() + s.name()
                   + " (" + QString::number(ng->skillRank(s)) + "): "
                   + s.level().valueString(ng->skillRank(s),ng)
                   + "\n");
  }
  ui->l_initative->setText(levelString(ng->characteristic(ed::Char_Initiative)));

  ui->l_death->setText(QString::number(ng->characteristic(ed::Char_Death)));
  ui->l_unconsious->setText(QString::number(ng->characteristic(ed::Char_Uncounciousness)));
  ui->l_injury->setText(QString::number(ng->characteristic(ed::Char_Injury)));

  ui->l_physicalDef->setText(QString::number(ng->characteristic(ed::Char_PhysicalDefense)) + " (" + QString::number(Database::requiredResult(ng->characteristic(ed::Char_PhysicalDefense),ed::Excellent)) + ")");
  ui->l_magicalDef->setText(QString::number(ng->characteristic(ed::Char_MagicDefense)) + " (" + QString::number(Database::requiredResult(ng->characteristic(ed::Char_MagicDefense),ed::Excellent)) + ")");
  ui->l_socialDef->setText(QString::number(ng->characteristic(ed::Char_SocialDefense)) + " (" + QString::number(Database::requiredResult(ng->characteristic(ed::Char_SocialDefense),ed::Excellent)) + ")");

  ui->l_physicalArmor->setText(QString::number(ng->characteristic(ed::Char_PhysicalArmor)));
  ui->l_mysticalArmor->setText(QString::number(ng->characteristic(ed::Char_MysticalArmor)));

  ui->l_move->setText(QString::number(ng->characteristic(ed::Char_WalkSpeed)) + " / " + QString::number(ng->characteristic(ed::Char_RunSpeed)));
  if (ng->race() == ed::Race_Sylphelin)
    ui->l_move->setText(ui->l_move->text() + " (" + QString::number(ng->characteristic(ed::Char_FlightSpeed)) + " / " + QString::number(ng->characteristic(ed::Char_FlightRunSpeed)) + ")");

  ui->l_recuperationCount->setText(QString::number(ng->characteristic(ed::Char_RecuperationCount)));

  ui->l_karma->setVisible(isAdept);
  ui->l_karmaLevel->setVisible(isAdept);
  ui->grp_spells->setVisible(isAdept && !a->spells().isEmpty());
  ui->grp_talents->setVisible(isAdept);

  QString racials;
  switch(ng->race())
  {
  case ed::Race_Elfe:
    racials = "Vision nocturne";
    break;
  case ed::Race_Humain:
    racials = "Polyvalence";
    break;
  case ed::Race_Nain:
    racials = "Vision thermographique";
    break;
  case ed::Race_Obsidien:
    racials = "Armure naturelle, Seuil de blessure accru (+3)";
    break;
  case ed::Race_Ork:
    racials = "Gahad, Vision nocturne";
    break;
  case ed::Race_Sylphelin:
    racials = "Défense physique accrue (+2), Sensibilité astrale, Vol";
    break;
  case ed::Race_Troll:
    racials = "Vision thermographique";
    break;
  case ed::Race_Tskrang:
    racials = "Attaque caudale";
    break;
  }

  ui->lbl_notes->setText(ng->name() + QString::fromUtf8(" possède les aptitudes raciales suivantes: ") + racials + ".");

  if (isAdept)
  {
    ui->lbl_race->setText(ui->lbl_race->text() + " - " + a->discipline().name() + " (" + QString::number(a->circle()) + ")");
    ui->l_karma->setNum(a->maximumKarma());
    ui->l_karmaLevel->setText(levelString(a->karmaLevel()));
    foreach(const Talent& t, a->talents())
    {
      ui->lbl_talents->setText(ui->lbl_talents->text()
                               +
                               t.name()
                               + (a->discipline().isDiscipline(t) ? QString::fromUtf8("D") : "")
                               + " (" + QString::number(a->talentRank(t)) + "): "
                               + t.level().valueString(a->talentRank(t),a) + "\n");
    }

    foreach(const Spell& s, a->spells())
    {
      ui->lbl_spells->setText(ui->lbl_spells->text() + s.name() + ", ");
    }

    foreach(const QString& k, a->karmaUsages()) ui->lbl_notes->setText(ui->lbl_notes->text() + "\nKarma utilisable sur les tests de " + k);
  }

  generateCsv(ng,a);
  generateIdd(ng,a);
}

void CharacterWidget::clear()
{
  ui->grp_talents->hide();
  ui->grp_spells->hide();
  ui->lbl_skills->clear();
  ui->lbl_talents->clear();
  ui->lbl_spells->clear();
}

void CharacterWidget::generateCsv(NameGiver *ng, Adept *a)
{
  bool isAdept = a != nullptr;

  const QString COL = ";";
  const QString ROW = "\n";
  _csv = ng->name() + ROW;
  _csv += ui->lbl_race->text() + ROW;

  _csv += "Attributs" + ROW;
  _csv += "DEX: " + ui->lbl_DEX->text() + COL + "FOR: " + ui->lbl_FOR->text() + COL + "CON: " + ui->lbl_CON->text() + ROW;
  _csv += "PER: " + ui->lbl_PER->text() + COL + "VOL: " + ui->lbl_VOL->text() + COL + "CHA: " + ui->lbl_CHA->text() + ROW;

  _csv += QString::fromUtf8("Caractéristiques") + ROW;
  _csv += "Initiative: " + ui->l_initative->text() + COL + COL + QString::fromUtf8("Déf. physique: ") + ui->l_physicalDef->text() + ROW;
  _csv += "Actions: 1" + COL + COL + QString::fromUtf8("Déf. magique: ") + ui->l_magicalDef->text() + ROW;
  _csv += "Attaque: " + COL + COL + QString::fromUtf8("Déf. sociale: ") + ui->l_socialDef->text() + ROW;

  _csv += QString::fromUtf8("Dégats: ") + COL + COL + "Arm. physique: " + ui->l_physicalArmor->text() + ROW;
  _csv += COL + COL + "Arm. mystique: " + ui->l_physicalArmor->text() + ROW;
  _csv += "Seuil de mort: " + ui->l_death->text() + COL + COL + QString::fromUtf8("Tests de récupération: ") + ui->l_recuperationCount->text() + ROW;
  _csv += "Seuil d'inconscience: " + ui->l_unconsious->text() + COL + COL + ROW;
  _csv += "Seuil de blessure grave: " + ui->l_injury->text() + COL + COL + QString::fromUtf8("Déplacement: ") + ui->l_move->text() + ROW;

  if (isAdept) _csv += "Points de karma: " + ui->l_karma->text() + COL + COL + QString::fromUtf8("Niveau/dé de karma: ") + ui->l_karmaLevel->text() + ROW;

  if (isAdept)
  {
    _csv += "Talents:" + ROW;
    _csv += "\"" + ui->lbl_talents->text() + "\"" + ROW;
  }

  _csv += QString::fromUtf8("Compétences:") + ROW;
  _csv += "\"" + ui->lbl_skills->text() + "\"" + ROW;

  _csv += QString::fromUtf8("Notes:") + ROW;
  _csv += "\"" + ui->lbl_notes->text() + "\"" + ROW;
}

QDomElement addElement(QDomDocument& doc, const QString& tagName, const QString& text, int ncols, int nrows)
{
  QDomElement result = doc.createElement(tagName);
  result.setAttribute("aid:crows",QString::number(nrows));
  result.setAttribute("aid:ccols",QString::number(ncols));
  result.setAttribute("aid:ccolwidth",QString::number(57.5));
  result.setAttribute("aid:table","cell");
  QDomText txt = doc.createTextNode(text);
  result.appendChild(txt);
  return result;
}
void addHeader(QDomDocument& doc, const char* text, QDomElement& parent)
{
  QString txt = QString::fromUtf8(text);
  parent.appendChild(addElement(doc, "Header", txt, 4, 1));
}
void addCell(QDomDocument& doc, const QString& text, QDomElement& parent, int w=2)
{
  parent.appendChild(addElement(doc, "Cell", text, w, 1));
}
void addCell(QDomDocument& doc, const char* header, QLabel* lbl, QDomElement& parent, int w=2)
{
  addCell(doc, QString::fromUtf8(header) + ": " + lbl->text(), parent, w);
}

void addEmptyCell(QDomDocument& doc, QDomElement& parent)
{
  addCell(doc,"",parent);
}

void CharacterWidget::generateIdd(NameGiver *ng, Adept *a)
{
  bool isAdept = a != nullptr;

  QDomDocument doc;
  QDomElement e_Root = doc.createElement("Root");
  QDomElement e_Story = doc.createElement("Story");
  QDomElement e_Character = doc.createElement("Character");
  e_Character.setAttribute("xmlns:aid","http://ns.adobe.com/AdobeInDesign/4.0/");
  e_Character.setAttribute("aid:table","table");
  e_Character.setAttribute("aid:trows","28");
  e_Character.setAttribute("aid:tcols","4");

  addHeader(doc,"Attributs", e_Character);
  addCell(doc,"DEX",ui->lbl_DEX, e_Character, 1);
  addCell(doc,"FOR",ui->lbl_FOR, e_Character, 1);
  addCell(doc,"CON",ui->lbl_CON, e_Character, 1);
  addCell(doc,"",e_Character, 1);

  addCell(doc,"PER",ui->lbl_PER, e_Character, 1);
  addCell(doc,"VOL",ui->lbl_VOL, e_Character, 1);
  addCell(doc,"CHA",ui->lbl_CHA, e_Character, 1);
  addCell(doc,"",e_Character, 1);

  addHeader(doc,"Caractéristiques", e_Character);

  addCell(doc,"Initiative",ui->l_initative,e_Character);
  addCell(doc,"Déf. physique",ui->l_physicalDef,e_Character);

  addCell(doc,"Actions:",e_Character);
  addCell(doc,"Déf. magique",ui->l_magicalDef,e_Character);

  addCell(doc,"Attaque:",e_Character);
  addCell(doc,"Déf. sociale",ui->l_socialDef,e_Character);

  addCell(doc,"Dégats:",e_Character);
  addCell(doc,"Arm. physique",ui->l_physicalArmor,e_Character);

  addEmptyCell(doc,e_Character);
  addCell(doc,"Arm. mystique",ui->l_mysticalArmor,e_Character);

  addCell(doc,"Seuil de mort",ui->l_death,e_Character);
  addCell(doc,"Tests de récupération",ui->l_recuperationCount,e_Character);

  addCell(doc,"Seuil d'inconscience",ui->l_unconsious,e_Character);
  addCell(doc,"",e_Character);

  addCell(doc,"Seuil de blessure grave",ui->l_injury,e_Character);
  addCell(doc,"Déplacement",ui->l_move,e_Character);

  addCell(doc,"",e_Character);
  addCell(doc,"",e_Character);

  if (isAdept)
  {
    addCell(doc,"Points de karma",ui->l_karma,e_Character);
    addCell(doc,"Niveau / dé de karma",ui->l_karmaLevel,e_Character);

    addHeader(doc,"Talents", e_Character);
    addCell(doc,ui->lbl_talents->text(),e_Character,4);
  }

  addHeader(doc,"Compétences", e_Character);
  addCell(doc,ui->lbl_skills->text(),e_Character,4);

  if (isAdept)
  {
    addHeader(doc,"Sorts", e_Character);
    addCell(doc,ui->lbl_spells->text(),e_Character,4);
  }

  addHeader(doc,"Butin", e_Character);
  addCell(doc,"",e_Character,4);

  addHeader(doc,"Points de légende", e_Character);
  addCell(doc,"",e_Character,4);

  addHeader(doc,"Équipement", e_Character);
  addCell(doc,"",e_Character,4);

  addHeader(doc,"Notes", e_Character);
  addCell(doc,ui->lbl_notes->text(),e_Character,4);

  e_Story.appendChild(e_Character);
  e_Root.appendChild(e_Story);
  doc.appendChild(e_Root);

  _idd = doc.toString();
}
